package com.example.day29_music_clip;

import android.annotation.SuppressLint;
import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Description:
 * Created by ZhDu on 2021/1/4 14:01.
 */
public class MusicProcess {
    @SuppressLint("WrongConstant")
    public void clip(String musicPath, String outPath, int startTime, int endTime) {
        if (endTime < startTime) {
            return;
        }
        //音频解封装  将MP3解成aac
        MediaExtractor mediaExtractor = new MediaExtractor();
        try {
            mediaExtractor.setDataSource(musicPath);
            int audioTrackIndex = selectTrack(mediaExtractor);
            mediaExtractor.selectTrack(audioTrackIndex);//将封装格式指向音频通道
            //跳到开始剪辑的位置
            mediaExtractor.seekTo(startTime, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
            MediaFormat oriAudioFormat = mediaExtractor.getTrackFormat(audioTrackIndex);
            int maxBufferSize = 100 * 1000;//一次读取的最大字节数，100k
            if (oriAudioFormat.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
                maxBufferSize = oriAudioFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
            } else {
                maxBufferSize = 100 * 1000;
            }
            ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
            MediaCodec mediacodec = MediaCodec.createDecoderByType(oriAudioFormat.getString(MediaFormat.KEY_MIME));
            //设置解码信息 直接从音频文件获取
            mediacodec.configure(oriAudioFormat,null,null,0);
            File pcmFile = new File(Environment.getExternalStorageDirectory(),"out.pcm");
            FileChannel writeChannel = new FileOutputStream(pcmFile).getChannel();
            mediacodec.start();
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            int outputBufferIndex = -1;
            while (true){
                int decodeInputIndex = mediacodec.dequeueInputBuffer(100000);
                if (decodeInputIndex >= 0) {
                    //获取采样时间
                    long sampleTime = mediaExtractor.getSampleTime();
                    if (sampleTime == -1) {
                        break;
                    }else if (sampleTime < startTime) {
                        mediaExtractor.advance();//释放掉数据
                        continue;
                    }else if (sampleTime > endTime) {
                        break;
                    }
                    //获取到压缩数据
                    info.size = mediaExtractor.readSampleData(buffer,0);
                    info.presentationTimeUs=sampleTime;
                    info.flags=mediaExtractor.getSampleFlags();

                    byte[] content = new byte[buffer.remaining()];
                    buffer.get(content);
                    FileUtils.writeContent(content);//输出到文件
                    //解码
                    ByteBuffer inputBuffer = mediacodec.getInputBuffer(decodeInputIndex);
                    inputBuffer.put(content);
                    mediacodec.queueInputBuffer(decodeInputIndex,0,info.size,info.presentationTimeUs,info.flags);
                    //释放上一帧的压缩数据
                    mediaExtractor.advance();
                }
                outputBufferIndex = mediacodec.dequeueOutputBuffer(info, 100_000);
                while (outputBufferIndex>=0){
                    ByteBuffer decodeOutputBuffer = mediacodec.getOutputBuffer(outputBufferIndex);
                    writeChannel.write(decodeOutputBuffer);//输出到out.pcm
                    mediacodec.releaseOutputBuffer(outputBufferIndex,false);
                    outputBufferIndex = mediacodec.dequeueOutputBuffer(info,100_000);
                }
            }
            writeChannel.close();
            mediaExtractor.release();
            mediacodec.stop();
            mediacodec.release();
            //转换MP3    pcm数据转换成mp3封装格式
            File wavFile = new File(Environment.getExternalStorageDirectory(),"output.mp3");
            new PcmToWavUtil(44100, AudioFormat.CHANNEL_IN_STEREO,2,
                    AudioFormat.ENCODING_PCM_16BIT).pcmToWav(pcmFile.getAbsolutePath(),wavFile.getAbsolutePath());
            Log.i("MusicProcess","转换完毕...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //一个音频文件里有很多个通道，找到音频通道
    private int selectTrack(MediaExtractor mediaExtractor) {
        //获取所有通道数
        int trackCount = mediaExtractor.getTrackCount();
        for (int i = 0; i < trackCount; i++) {
            MediaFormat trackFormat = mediaExtractor.getTrackFormat(i);
            //获取通道当前的格式
            String mime = trackFormat.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("audio/")) {
                return i;
            }
        }
        return -1;
    }

}
